package com.bidevalution.business.job;

import com.bidevalution.business.context.StepType;
import com.bidevalution.business.factory.StepJobJdbcFactory;
import com.bidevalution.business.service.JdbcTemplateService;
import com.bidevalution.dao.entity.*;
import com.bidevalution.support.context.Constants;
import com.bidevalution.support.context.EvalutionMethodEnum;
import com.google.common.collect.Maps;
import com.qtp.core.util.DateUtil;
import com.qtp.core.util.IdsUtil;
import com.qtp.core.util.OConvertUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.core.namedparam.SqlParameterSourceUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @description:商务评审分数计算（直线插入法）
 * @author: xiayf
 * @date: 2019-12-05 19:37
 */
public class BusinessComputerScoreJob implements StepJobJdbcFactory {

    private Logger log = LogManager.getLogger(getClass());
    private JdbcTemplateService jdbcTemplateService;

    @Override
    public Boolean execute(BeSectionStepJob beSectionStepJob, String submitCode, String expertId, String layoutCode) throws Exception {
        try {
            Map<String, Object> paramMap = Maps.newHashMap();
            paramMap.put("stepType", StepType.Commercial.getCode());
            paramMap.put("sectionId", beSectionStepJob.getSectionId());
            Map<String, String> sectionParameterMap = Maps.newHashMap();
            StringBuilder sb = new StringBuilder();
            RowMapper<BeSectionParameter> rm = BeanPropertyRowMapper.newInstance(BeSectionParameter.class);
            List<BeSectionParameter> beSectionParameterList = jdbcTemplateService
                    .selectForList("SELECT param_id,param_value FROM be_section_parameter WHERE section_id=:sectionId",
                            paramMap, rm);
            //获取评标参数
            if (beSectionParameterList == null || beSectionParameterList.isEmpty()) {
                throw new Exception("*******没有查询到评标参数********");
            }
            for (BeSectionParameter beSectionParameter : beSectionParameterList) {
                sectionParameterMap.put(beSectionParameter.getParamId(), beSectionParameter.getParamValue());
            }
            //总分
            BigDecimal sumScore = new BigDecimal(sectionParameterMap.get("tbbj"));
            sb.setLength(0);
            sb.append(" SELECT distinct b.enterprise_id enterpriseId,b.biin_Total bidPrice ");
            sb.append(" FROM be_evalution_summary a  ");
            sb.append(" LEFT JOIN  td_bidinfo b ON a.enterprise_id=b.enterprise_id ");
            sb.append(" WHERE a.section_id=:sectionId AND is_del <> 1 AND is_passed=1 AND b.enterprise_id is not null");
            List<Map<String, Object>> dataList = jdbcTemplateService.selectForList(sb.toString(), paramMap);
            List<BeEvalutionScoreDetail> beEvalutionScoreDetailList = new ArrayList<>();
            BeEvalutionScoreDetail beEvalutionScoreDetail;
            for (Map<String, Object> dataMap : dataList) {
                //得分
                BigDecimal score = sumScore;
                beEvalutionScoreDetail = new BeEvalutionScoreDetail();
                beEvalutionScoreDetail.setSeqId(IdsUtil.uuid());
                beEvalutionScoreDetail.setSectionId(beSectionStepJob.getSectionId());
                //商务
                beEvalutionScoreDetail.setStepType(StepType.Commercial.getCode());
                beEvalutionScoreDetail.setEnterpriseId(OConvertUtils.getString(dataMap.get("enterpriseId")));
                beEvalutionScoreDetail.setExpertId(IdsUtil.emptyGuid());
                beEvalutionScoreDetail.setCreateTime(DateUtil.now());
                beEvalutionScoreDetail.setUpdateTime(DateUtil.now());
                //投标报价
                BigDecimal bidPrice = new BigDecimal(OConvertUtils.getString(dataMap.get("bidPrice"), "0")).setScale(Constants.ZERO, BigDecimal.ROUND_HALF_UP);
                if (EvalutionMethodEnum.JLZH.getCode().equals(beSectionStepJob.getJobContent())) {
                    //施工监理综合评估法
                    score = computerSgjlScore(sectionParameterMap, sumScore, score,
                            new BigDecimal(sectionParameterMap.get("basicPrice")).setScale(Constants.ZERO, BigDecimal.ROUND_HALF_UP),
                            new BigDecimal(sectionParameterMap.get("cardNo")).setScale(Constants.ZERO, BigDecimal.ROUND_HALF_UP), bidPrice);
                } else if (EvalutionMethodEnum.SJZH_ZGHS.getCode().equals(beSectionStepJob.getJobContent()) ||
                        EvalutionMethodEnum.SJZH_ZGYS.getCode().equals(beSectionStepJob.getJobContent())) {
                    //设计综合评估法（适用于资格后审项目）和设计综合评估法（适用于资格预审项目）
                    score = computerSjzhZghsScore(sectionParameterMap, sumScore, score,
                            new BigDecimal(sectionParameterMap.get("basicPrice")).setScale(Constants.ZERO, BigDecimal.ROUND_HALF_UP), bidPrice);
                } else if (EvalutionMethodEnum.GCZCBZH_ZGYS.getCode().equals(beSectionStepJob.getJobContent()) ||
                        EvalutionMethodEnum.GCZCBZH_ZGHS.getCode().equals(beSectionStepJob.getJobContent())) {
                    //工程总承包综合评估法（适用于资格预审项目）和工程总承包综合评估法（适用于资格后审项目）
                    score = computerGczcbScore(sectionParameterMap, sumScore, score,
                            new BigDecimal(sectionParameterMap.get("zjbj")).setScale(Constants.ZERO, BigDecimal.ROUND_HALF_UP),
                            new BigDecimal(sectionParameterMap.get("cardNo")).setScale(Constants.ZERO, BigDecimal.ROUND_HALF_UP), bidPrice);
                }
                beEvalutionScoreDetail.setScore(OConvertUtils.getString(score.compareTo(new BigDecimal(0)) == Constants.MINUSONE ? 0 : score));
                beEvalutionScoreDetailList.add(beEvalutionScoreDetail);
            }
            //批量转数组
            SqlParameterSource[] beanSources = SqlParameterSourceUtils.createBatch(beEvalutionScoreDetailList);
            //删除已存在结果
            jdbcTemplateService.update(" DELETE FROM be_evalution_score_detail WHERE section_id=:sectionId AND step_type =:stepType ", paramMap);
            //批量插入
            jdbcTemplateService.bathInsert(" INSERT INTO be_evalution_score_detail(seq_id, enterprise_id, section_id, expert_id, score, step_type, create_time, update_time) " +
                    " VALUES(:seqId, :enterpriseId, :sectionId,:expertId,:score,:stepType,:createTime,:updateTime) ", beanSources);
            //批量更新
            jdbcTemplateService.bathUpdate(" UPDATE be_section_enterprise SET business_score=:score WHERE seq_id=:enterpriseId", beanSources);
            return true;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new Exception("*****商务评审分数计算（直线插入法）失败*****");
        }
    }

    /**
     * 计算施工监理综合评估法的商务标得分
     *
     * @param sectionParameterMap 评标参数
     * @param sumScore            商务总分
     * @param score               商务得分
     * @param basicPrice          评标基准价
     * @param cardNo              风险控制价
     * @param bidPrice            投标报价
     * @return
     */
    private BigDecimal computerSgjlScore(Map<String, String> sectionParameterMap, BigDecimal sumScore, BigDecimal score,
                                         BigDecimal basicPrice, BigDecimal cardNo, BigDecimal bidPrice) throws Exception {
        try {
            if (bidPrice.compareTo(basicPrice) == Constants.ONE) {
                //投标报价高于评标基准价
                //得分=总分-((((投标报价-基准价)/基准价)*100)/(扣分比例))*扣分基数
                score = sumScore.subtract(((((bidPrice.subtract(basicPrice)).divide(basicPrice, Constants.FOUR, BigDecimal.ROUND_HALF_UP))
                        .multiply(new BigDecimal(100))).
                        divide((new BigDecimal(sectionParameterMap.get("graderate"))), Constants.TWENTY, BigDecimal.ROUND_HALF_UP).
                        multiply(new BigDecimal(sectionParameterMap.get("deductbase")))).setScale(Constants.TWO, BigDecimal.ROUND_HALF_UP));
            } else if (bidPrice.compareTo(basicPrice) == Constants.MINUSONE) {
                //投标报价低于于评标基准价
                //得分=总分-((((基准价-投标报价)/基准价)*100)/(扣分比例))*扣分基数
                score = sumScore.subtract(((((basicPrice.subtract(bidPrice)).divide(basicPrice, Constants.FOUR, BigDecimal.ROUND_HALF_UP))
                        .multiply(new BigDecimal(100))).
                        divide((new BigDecimal(sectionParameterMap.get("graderate0"))), Constants.TWENTY, BigDecimal.ROUND_HALF_UP).
                        multiply(new BigDecimal(sectionParameterMap.get("deductbase0")))).setScale(Constants.TWO, BigDecimal.ROUND_HALF_UP));
                if (bidPrice.compareTo(cardNo) == Constants.MINUSONE) {
                    //投标报价低于风险控制价
                    //得分=低于评标基准价计算的得分-((((风险控制价-投标报价)/风险控制价)*100)/(扣分比例))*扣分基数
                    score = score.subtract(((((cardNo.subtract(bidPrice)).divide(cardNo, Constants.FOUR, BigDecimal.ROUND_HALF_UP))
                            .multiply(new BigDecimal(100))).
                            divide((new BigDecimal(sectionParameterMap.get("graderate1"))), Constants.TWENTY, BigDecimal.ROUND_HALF_UP).
                            multiply(new BigDecimal(sectionParameterMap.get("deductbase1")))).setScale(Constants.TWO, BigDecimal.ROUND_HALF_UP));
                }
            }
            return score;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw e;
        }
    }

    /**
     * 计算设计综合评估法（适用于资格(预/后)审项目）的商务标得分
     *
     * @param sectionParameterMap 评标参数
     * @param sumScore            商务总分
     * @param score               商务得分
     * @param basicPrice          评标基准价
     * @param bidPrice            投标报价
     * @return
     */
    private BigDecimal computerSjzhZghsScore(Map<String, String> sectionParameterMap, BigDecimal sumScore, BigDecimal score,
                                             BigDecimal basicPrice, BigDecimal bidPrice) throws Exception {
        try {
            if (bidPrice.compareTo(basicPrice) == Constants.ONE) {
                //投标报价高于评标基准价
                //得分=总分-((((投标报价-基准价)/基准价)*100)/(扣分比例))*扣分基数
                score = sumScore.subtract(((((bidPrice.subtract(basicPrice)).divide(basicPrice, Constants.FOUR, BigDecimal.ROUND_HALF_UP))
                        .multiply(new BigDecimal(100))).
                        divide((new BigDecimal(sectionParameterMap.get("graderate"))), Constants.TWENTY, BigDecimal.ROUND_HALF_UP).
                        multiply(new BigDecimal(sectionParameterMap.get("deductbase")))).setScale(Constants.TWO, BigDecimal.ROUND_HALF_UP));
            } else if (bidPrice.compareTo(basicPrice) == Constants.MINUSONE) {
                //投标报价低于于评标基准价
                //得分=总分-((((基准价-投标报价)/基准价)*100)/(扣分比例))*扣分基数
                score = sumScore.subtract(((((basicPrice.subtract(bidPrice)).divide(basicPrice, Constants.FOUR, BigDecimal.ROUND_HALF_UP))
                        .multiply(new BigDecimal(100))).
                        divide((new BigDecimal(sectionParameterMap.get("graderate0"))), Constants.TWENTY, BigDecimal.ROUND_HALF_UP).
                        multiply(new BigDecimal(sectionParameterMap.get("deductbase0")))).setScale(Constants.TWO, BigDecimal.ROUND_HALF_UP));
            }
            return score;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw e;
        }
    }

    /**
     * 计算工程总承包综合评估法（适用于资格(预/后)审项目）的商务标得分
     *
     * @param sectionParameterMap 评标参数
     * @param sumScore            商务总分
     * @param score               商务得分
     * @param basicPrice          最佳报价
     * @param cardNo              风险控制价
     * @param bidPrice            投标报价
     * @return
     */
    private BigDecimal computerGczcbScore(Map<String, String> sectionParameterMap, BigDecimal sumScore, BigDecimal score,
                                          BigDecimal basicPrice, BigDecimal cardNo, BigDecimal bidPrice) throws Exception {
        try {
            if (bidPrice.compareTo(basicPrice) != Constants.ZERO) {
                //投标报价高于或低于最佳报价
                //得分=总分-((((投标报价-最佳报价的绝对值)/最佳报价)*100)/(扣分比例))*扣分基数
                score = sumScore.subtract((((((basicPrice.subtract(bidPrice)).abs()).divide(basicPrice, Constants.FOUR, BigDecimal.ROUND_HALF_UP))
                        .multiply(new BigDecimal(100))).
                        divide((new BigDecimal(sectionParameterMap.get("graderate"))), Constants.TWENTY, BigDecimal.ROUND_HALF_UP).
                        multiply(new BigDecimal(sectionParameterMap.get("deductbase")))).setScale(Constants.TWO, BigDecimal.ROUND_HALF_UP));
                if (bidPrice.compareTo(cardNo) == Constants.MINUSONE) {
                    //投标报价低于风险控制价
                    //得分=总分-((((最佳报价-投标报价)/最佳报价)*100)/(扣分比例))*扣分基数
                    score = sumScore.subtract(((((basicPrice.subtract(bidPrice)).divide(basicPrice, Constants.FOUR, BigDecimal.ROUND_HALF_UP))
                            .multiply(new BigDecimal(100))).
                            divide((new BigDecimal(sectionParameterMap.get("graderate1"))), Constants.TWENTY, BigDecimal.ROUND_HALF_UP).
                            multiply(new BigDecimal(sectionParameterMap.get("deductbase1")))).setScale(Constants.TWO, BigDecimal.ROUND_HALF_UP));
                }
            }
            return score.setScale(Constants.TWO, BigDecimal.ROUND_HALF_UP);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw e;
        }
    }

    @Override
    public void setJdbcTemplateService(JdbcTemplateService jdbcTemplateService) {
        this.jdbcTemplateService = jdbcTemplateService;
    }
}
